﻿from Tkinter import *
from Canvas import *
import sys
import os

WIDTH  = 400 # width of canvas
HEIGHT = 400 # height of canvas

HPSIZE = 2 # half of point size (must be integer)
CCOLOR = "#0000FF" # blue

elementList = [] # list of elements (used by Canvas.delete(...))

polygonA = []
polygonB = []
# Urbild- und Abbildungs-Polygon

polygon = [[50,50],[350,50],[350,350],[50,350],[50,50]]
# aktuelles polygon das gezeichnet wird

time = 0
dt = 0.01

def polygonSnapshot():
    """Setzt Punkte für naechsten Schnappschuss des morphenden Polygons"""
    # Wichtigster Schritt, der Punkt aus dem Urbild und der Punkt aus dem Abbild
    # welche gegeneinander gemorpht werden sollen werden in ein tupel gestopft.
    # Nun soll sich der X Wert (x1) des Urbildpunkts langsam an den X Wert des
    # Abbildpunkts annaehern. Dazu wird der faktor Zeit benutzt um beide Werte
    # so zu verringern, dass sie addiert langsam auf den Abbildpunk zulaufen.
    # Das selbe für den X Wert (x2).
    # zurueckgegeben wird eine Liste von Punkten wobei die Punkte der Form [x1,x2]
    # sind. Also eine Liste von Listen.
    # IMMER ZEICHNEN.
    ret = []
    for tup in zip(polygonA, polygonB):
        # tup besteht aus dem Punkt des Urbilds und dem des Abbilds die zusammengehoeren
        x1 = (1-time)*tup[0][0] + time*tup[1][0] # e1 Werte morphen
        x2 = (1-time)*tup[0][1] + time*tup[1][1] # e2 Werte morphen
        ret.append([x1,x2])
    return ret        
    
def drawObjekts():
    """ draw polygon and points """
    # TODO: inpterpolate between polygons and render
    polygon = polygonSnapshot()
    
    for (p,q) in zip(polygon,polygon[1:]):
        elementList.append(can.create_line(p[0], p[1], q[0], q[1],
                                           fill=CCOLOR))
    # Linie zeichnen
        elementList.append(can.create_oval(p[0]-HPSIZE, p[1]-HPSIZE,
                                           p[0]+HPSIZE, p[1]+HPSIZE,
                                           fill=CCOLOR, outline=CCOLOR))
    # Punkte einzeichnen
            
def quit(root=None):
    """ quit programm """
    if root==None:
        sys.exit(0)
    root._root().quit()
    root._root().destroy()


def draw():
    """ draw elements """
    can.delete(*elementList)
    del elementList[:]
    drawObjekts()
    can.update()


def forward():
    """startet morph zum polygon B"""
    global time
    while(time<1):
        time += dt
        # TODO: interpolate ?        
        print time
        draw()


def backward():
    global time
    while(time>0):
        time -= dt
        # TODO: interpolate 
        print time
        draw()
    

if __name__ == "__main__":
    # check parameters
##    if len(sys.argv) != 3:
##       print "morph.py firstPolygon secondPolygon"
##       sys.it(-1)

    # TODOS:
    # - read in polygons
        
##    f1 = sys.argv[1]
##    f2 = sys.argv[2]
    f1 = 'polygonA.dat'
    f2 = 'polygonZ.dat'

    polygonA = [map(float,line.split()) for line in file(f1)]
    polygonB = [map(float,line.split()) for line in file(f2)]
    # assert - jeweils Liste von 2elementigen Listen mit Koordinaten
    
    # - transform from local into global coordinate system 
    polygonA = [[u1*WIDTH, HEIGHT - u2*HEIGHT] for (u1,u2) in polygonA]
    polygonB = [[u1*WIDTH, HEIGHT - u2*HEIGHT ] for (u1,u2) in polygonB]
    # x2 Werte (Y-Koordinaten) umrechnen da Bild von oben links aufgebaut wird
    # assert - für jedes Polygon existiert eine Liste mit korrekten Koordinaten
    # für das fertige Polygon
    
    # zu zeichnedes polygon    
    polygon = polygonB
    
    
    # - make both polygons contain same number of points
    # einen Punk hinzufuegen der nichts zerstoert aber sein pendant erzeugen kann
    diff = len(polygonA) - len(polygonB)    
    if diff:
        if diff < 0: # A kuerzer als Z
            polygonA.append(polygonA[-1])
        else:   # B kuerzer als A
            polygonB.append(polygonB[-1])
    # das Polygon mit weniger Punkten fuellt auf mit seinem letzten Punkt
    
    # create main window
    mw = Tk()
    mw._root().wm_title("Morphing")

    # create and position canvas and buttons
    cFr = Frame(mw, wid
                th=WIDTH, height=HEIGHT, relief="sunken", bd=1)
    cFr.pack(side="top")
    can = Canvas(cFr, width=WIDTH, height=HEIGHT)
    can.pack()
    cFr = Frame(mw)
    cFr.pack(side="left")
    bClear = Button(cFr, text="backward", command=backward)
    bClear.pack(side="left")
    bClear = Button(cFr, text="forward", command=forward)
    bClear.pack(side="left")
    eFr = Frame(mw)
    eFr.pack(side="right")
    bExit = Button(eFr, text="Quit", command=(lambda root=mw: quit(root)))
    bExit.pack()
    draw()
    
    # start
    mw.mainloop()
    
